/* * jPOS Project [http://jpos.org] * Copyright (C) 2000-2017 jPOS Software SRL * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.jpos.transaction.participant; import bsh.EvalError; import org.jdom2.Element; import org.jpos.core.ConfigurationException; import org.jpos.core.XmlConfigurable; import org.jpos.transaction.AbortParticipant; import org.jpos.transaction.TransactionParticipant; import org.jpos.util.LogEvent; import org.jpos.util.Logger; import org.jpos.util.SimpleLogSource; import java.io.IOException; import java.io.Serializable; import java.util.HashMap; import java.util.Map; /** A TransactionParticipant whose prepare, commit and abort methods can be * specified through beanshell scripts. <BR> * * To indicate what code to execute for any of the methods just add an element * named 'prepare', 'commit' or 'abort' contained in that of the participant. <BR> * * See BSHMethod for details on the syntax of these elements. The value to return * in the prepare method should be stored in the script variable named "result". * None of these tags are mandatory. <BR> * * You can subclass BSHTransactionParticipant and override the default... * methods. That way you can provide default behaviour for a participant and * override it at deploy time through scripts. * * @see BSHMethod * @author AMarques */ @SuppressWarnings("unchecked") public class BSHTransactionParticipant extends SimpleLogSource implements TransactionParticipant, AbortParticipant, XmlConfigurable { protected BSHMethod prepareMethod; protected BSHMethod prepareForAbortMethod; protected BSHMethod commitMethod; protected BSHMethod abortMethod; boolean trace; /** Creates a new instance of BSHTransactionParticipant */ public BSHTransactionParticipant() { super(); } public void abort(long id, java.io.Serializable context) { LogEvent ev = new LogEvent(this, "abort"); if (abortMethod != null) { try { executeMethod(abortMethod, id, context, ev, ""); } catch (Exception ex) { ev.addMessage(ex); } } else { defaultAbort(id, context, ev); } if (trace) Logger.log(ev); } protected void defaultAbort(long id, Serializable context, LogEvent ev) {} public void commit(long id, java.io.Serializable context) { LogEvent ev = new LogEvent(this, "commit"); if (commitMethod != null) { try { executeMethod(commitMethod, id, context, ev, ""); } catch (Exception ex) { ev.addMessage(ex); } } else { defaultCommit(id, context, ev); } if (trace) Logger.log(ev); } protected void defaultCommit(long id, Serializable context, LogEvent ev) {} public int prepare(long id, java.io.Serializable context) { LogEvent ev = new LogEvent(this, "prepare"); int result = ABORTED | READONLY; if (prepareMethod != null) { try { result = (Integer) executeMethod(prepareMethod, id, context, ev, "result"); } catch (Exception ex) { ev.addMessage(ex); } } else { result = defaultPrepare(id, context, ev); } ev.addMessage("result", Integer.toBinaryString(result)); if (trace) Logger.log(ev); return result; } public int prepareForAbort(long id, java.io.Serializable context) { LogEvent ev = new LogEvent(this, "prepare-for-abort"); int result = ABORTED | READONLY; if (prepareForAbortMethod != null) { try { result = (Integer) executeMethod(prepareForAbortMethod, id, context, ev, "result"); } catch (Exception ex) { ev.addMessage(ex); } } ev.addMessage("result", Integer.toBinaryString(result)); if (trace) Logger.log(ev); return result; } protected int defaultPrepare(long id, Serializable context, LogEvent ev) { return PREPARED | READONLY; } public void setConfiguration(Element e) throws ConfigurationException { try { prepareMethod = BSHMethod.createBshMethod(e.getChild("prepare")); prepareForAbortMethod = BSHMethod.createBshMethod(e.getChild("prepare-for-abort")); commitMethod = BSHMethod.createBshMethod(e.getChild("commit")); abortMethod = BSHMethod.createBshMethod(e.getChild("abort")); trace = "yes".equals (e.getAttributeValue ("trace")); } catch (Exception ex) { throw new ConfigurationException(ex.getMessage(), ex); } } protected Object executeMethod(BSHMethod m, long id, Serializable context, LogEvent evt, String resultName) throws EvalError, IOException { Map params = new HashMap(); params.put("context", context); params.put("id", id); params.put("evt", evt); params.put("self", this); return m.execute(params, resultName); } }